package cluster

import (
	"fmt"
	"github.com/emicklei/go-restful"
	"kubeInstall/pkg/logger"
	"kubeInstall/server/handlers"
	modelCluster "kubeInstall/server/models/cluster"
	"kubeInstall/server/services/cluster"
	"kubeInstall/server/services/host"
	"kubeInstall/server/services/storageplugin"
	"kubeInstall/utils/validate"
	"net/http"
	"strconv"
)

const MASTER = "master"
const WORKER = "worker"

type clusterHandler struct {
	handlers.BaseHandler
}

func NewClusterHandler() handlers.IBaseHandler {
	return new(clusterHandler)
}
func (h *clusterHandler) AddToRoute(ws *restful.WebService) {

	ws.Route(ws.POST("/cluster").To(h.createCluster))
	ws.Route(ws.GET("/cluster").To(h.listCluster))
	ws.Route(ws.GET("/cluster/{cluster_id}").To(h.getCluster))
	logger.Info("add cluster module successfully")
}

func (h *clusterHandler) listCluster(r *restful.Request, resp *restful.Response) {

	offset, _ := strconv.Atoi(r.QueryParameter("offset"))
	limit, _ := strconv.Atoi(r.QueryParameter("limit"))

	data, err := cluster.ListClusters(limit, offset)

	if err != nil {
		h.RenderError(resp, fmt.Sprintf("list user failed,error is: %v", err), http.StatusBadRequest)
		return
	}
	logger.Info("list cluster successfully")
	h.RenderResp(resp, data, http.StatusOK)

}
func (h *clusterHandler) validateCluster(clusterInfo *modelCluster.Cluster) error {

	if clusterInfo.ClusterName == "" || clusterInfo.DomainName == "" || clusterInfo.PodCIDR == "" || clusterInfo.SvcCIDR == "" {
		return fmt.Errorf("ClusterName ,DomainName ,PodCIDR ,SvcCIDR can not be null")
	}

	if clusterInfo.MaxPodNum > 100 || clusterInfo.MaxPodNum == 0 {
		clusterInfo.MaxPodNum = 100
	}

	if clusterInfo.StoragePlugin == nil {
		return fmt.Errorf("StoragePlugin can not be null")
	}

	if storageplugin.CheckNfsIdIsUsed(clusterInfo.StoragePlugin.ID) {
		return fmt.Errorf("Storage Plugin Id %s is already used ", clusterInfo.StoragePlugin.ID)
	}

	if clusterInfo.MasterNode == nil {
		return fmt.Errorf("MasterNode can not be null")
	}

	if clusterInfo.WorkerNode == nil {
		return fmt.Errorf("WorkerNode can not be null")
	}

	for _, h := range clusterInfo.MasterNode {

		if host.CheckHostIsUsed(h.ID) {
			return fmt.Errorf("host %s is already used ", h.ID)
		}

		if h.Role != MASTER {
			return fmt.Errorf("role of host %s is not master ", h.ID)
		}
	}

	for _, h := range clusterInfo.WorkerNode {

		if host.CheckHostIsUsed(h.ID) {
			return fmt.Errorf("host %s is already used ", h.ID)
		}

		if h.Role != WORKER {
			return fmt.Errorf("role of host %s is not worker ", h.ID)
		}
	}

	if validate.IsContainIllegalChar(clusterInfo.ClusterName, []string{",", "~", "#", "$", "%", "@"}) {
		return fmt.Errorf("ClusterName %s contains illegal characters", clusterInfo.ClusterName)
	}

	if validate.IsContainIllegalChar(clusterInfo.DomainName, []string{",", "~", "#", "$", "%", "@"}) {
		return fmt.Errorf("DomainName %s  contains illegal characters", clusterInfo.DomainName)
	}

	if err := validate.ValidateCIDR(clusterInfo.PodCIDR); err != nil {
		return err
	}
	if err := validate.ValidateCIDR(clusterInfo.SvcCIDR); err != nil {
		return err
	}

	return nil
}

func (h *clusterHandler) createCluster(r *restful.Request, resp *restful.Response) {
	//将前端用户配置好的集群信息，写入数据库。
	var req modelCluster.Cluster
	if err := r.ReadEntity(&req); err != nil {
		h.RenderError(resp, "read cluster info from http request failed", http.StatusBadRequest)
		return
	}

	if err := h.validateCluster(&req); err != nil {
		h.RenderError(resp, fmt.Sprintf("read cluster info failed. error is: %v", err), http.StatusBadRequest)
		return
	}

	//创建集群配置
	if req.ClusterVersion == "" {
		req.ClusterVersion = "1.18.3"
	}

	if req.ProxyMode == "" {
		req.ProxyMode = "ipvs"
	}

	if req.RepoName == "" {
		req.RepoName = "registry.aliyuncs.com/google_containers"
	}

	if req.NetworkType == "" {
		req.NetworkType = "calico"
	}

	master0, _ := host.GetHost(req.MasterNode[0].ID)
	if req.VipServer == "" {
		req.VipServer = master0.IP
		req.ApiServer = master0.IP
	}

	req.ClusterType = master0.HostType

	result, err := cluster.CreateCluster(&req)
	if err != nil {
		h.RenderError(resp, fmt.Sprintf("add cluster failed %v", err), http.StatusBadRequest)
		return
	}
	clusterInfo, err := h.getClusterInfo(result.ID)

	if err != nil {
		h.RenderError(resp, fmt.Sprintf("get cluster failed! error is:  %v", err), http.StatusBadRequest)
		return
	}

	h.RenderResp(resp, clusterInfo, http.StatusOK)

}

func (h *clusterHandler) getCluster(r *restful.Request, resp *restful.Response) {
	//读取数据库配置。返回集群信息
	clusterId := r.PathParameter("cluster_id")

	if clusterId == "" {
		h.RenderError(resp, fmt.Sprintf("get cluster id from http query failed!"), http.StatusBadRequest)
		return
	}

	clusterInfo, err := h.getClusterInfo(clusterId)

	if err != nil {
		h.RenderError(resp, fmt.Sprintf("get cluster failed! error is:  %v", err), http.StatusNotFound)
		return
	}

	h.RenderResp(resp, clusterInfo, http.StatusOK)

}
func (h *clusterHandler) getClusterInfo(clusterId string) (*modelCluster.Cluster, error) {

	clusterInfo, err := cluster.GetCluster(clusterId)
	if err != nil {
		return nil, err
	}

	//查询节点信息。
	if clusterInfo.StorageType == "nfs" {
		storage, err := storageplugin.GetStoragePluginNFSByClusterId(clusterId)
		if err != nil {
			return nil, err
		}

		clusterInfo.StoragePlugin = storage
	}

	masterNode, err := host.GetHostRoleByClusterId(clusterId, MASTER)
	if err != nil {
		return nil, err
	}

	workerNode, err := host.GetHostRoleByClusterId(clusterId, WORKER)
	if err != nil {
		return nil, err
	}

	hosts := make([]modelCluster.HostNameAndIP, 0)

	for _, m := range masterNode {

		h := modelCluster.HostNameAndIP{
			HostName: m.HostName,
			Ip:       m.IP,
		}
		hosts = append(hosts, h)
	}

	for _, m := range workerNode {
		h := modelCluster.HostNameAndIP{
			HostName: m.HostName,
			Ip:       m.IP,
		}
		hosts = append(hosts, h)
	}

	clusterInfo.MasterNode = masterNode
	clusterInfo.WorkerNode = workerNode
	clusterInfo.HostNameMap = hosts

	return clusterInfo, nil
}

func (h *clusterHandler) deleteCluster(r *restful.Request, resp *restful.Response) {
	//读取数据库配置。根据配置，使用kubeadm卸载集群。
}
